#include<fstream>
#include<iostream>
#include<string>
#include<sstream>
#include<map>
#include<set>
#include<vector>
using std::endl;
using std::cout;
using std::ifstream;
using std::string;
using std::map;
using std::istringstream;
using std::vector;
using std::set;

typedef struct line_s{
    string line;
    int _idx;//行号
}Line_t;

typedef struct word{
    string word;
    set<int> worldLine;//记录单词行号的
}Word;

class TextQuery
{
public:

void readFile(const string filename);
void query(const string & word);//读单词
//查单词 记录单词的个数
void readLine(Line_t&line);
//记录单词函数
void readWorldLine(const word &word,int ldx);
//遍历文章和句子
void writeLine(){
    for(auto &ln:_lines){
        cout<<"id:"<<ln._idx<<"  "<<ln.line<<endl;
    }
}
//遍历单词
void WriteWorld(){
    for(auto &wo:_dict){
        cout<<wo.first<<":  "<<wo.second<<endl;
    }
}
//find wordNum
void FindNum(const char*world){
    auto it = _dict.find(world);
    printf("%s occurs %d times\n",it->first.c_str(),it->second);
}

private:

vector<Line_t> _lines;//O(1)
map<string, set<int> > _wordNumbers;//the the
map<string, int> _dict;//
};
//读出一行一行的
void TextQuery::readFile(const string filename){
    int id = 0;  //记录个数
    string line; //记录语句
    Line_t _line;
    ifstream ifs(filename);
    if(!ifs.good()){
        cout<<"ifs open file fail!"<<endl;
        return;
    }
    while(std::getline(ifs,line)){
        id++;
        _line.line = line;
        _line._idx = id;
        _lines.push_back(_line);
        readLine(_line);
    }
}
//记录单词个数
//读单词的时候，就要记录行数  
void TextQuery::readLine(Line_t&line){
    string world;
    istringstream iss(line.line);
    Word word;//准备好记录
    while(iss>>world){
        if(ispunct(world.back())){
            //移除尾部标点符号
                world.erase(world.find(world.back()));
            }
        if(ispunct(world.front())){
            //移除头部标点符号
            world.erase(world.find(world.front()));
        }
        //大小写转换
        if(isupper(world[0])){
            world[0] = tolower(world[0]);
        }
        //如过该单词出现过，就不统计

        bool isExit = false;
        //该行出现过哈 一会儿要改
        for(auto &ele : _dict){
            if(world == ele.first){
                //出现过
                isExit = true;
                ++ele.second;
                break;
            }
        }
        if(isExit!=true){
            _dict.insert({world,1});
        }
        //记录单词和个数
        word.word = world;
        word.worldLine.insert(line._idx);
        readWorldLine(word,line._idx);
        
    }
}

//记录单词行数  //读单词的时候用
//记录一下这个单词的id 往这个world里面去+ world ldx
void TextQuery::readWorldLine(const word &word,int ldx){
    for(auto &ln :_wordNumbers){
        if(word.word == ln.first){
            ln.second.insert(ldx);
        }
    }
    _wordNumbers.insert({word.word,word.worldLine});
}



//查阅单词
void TextQuery::query(const string & word){
    auto it = _wordNumbers.find(word);
    FindNum(word.c_str());
    cout<<"-->"<<endl;
    string line;
    for(auto &ln: it->second){
        //cout<<ln<<endl;
        //根据行号打印
        for(auto &vln:_lines){
            if(ln == vln._idx){
                line = vln.line;
            }
        }
        printf("((line: %d) %s \n",ln,line.c_str());
    }
}

int main(void){
    TextQuery test;
    test.readFile("china_daily.txt");
    //test.writeLine();
    //test.WriteWorld();
    test.query("the");
}